from flask import Flask

from flask import Flask,jsonify

#导入蓝图
from apps.user.urls import user_bp
from apps.websocket.urls import ws_bp
from apps.resource.urls import resource_bp

#导入配置字典
from settings import envs
#导入restful对象
from ext import api
#导入跨域对象
from ext import cors
#导入db对象
from ext import db
#导入cache
from ext import cache
#导入中间件
from apps.middleware import after_request  #响应前执行的中间件
from apps.middleware import before_request
#导入日志
from util.logger import getLogHandlerFile
import logging
from gevent import monkey

#使用redis作为cache缓存
cache_config_redis = {
    'CACHE_TYPE':'redis',
    'CACHE_REDIS_HOST':'127.0.0.1',
    'CACHE_REDIS_PORT':6637,
    # 'CACHE_REDIS_PASSWORD':'密码', #如果redis配置了密码
    'CACHE_REDIS_DB':0, #指定使用的redis的db，默认0-15
}

#使用内存做cache缓存
cache_config_mem = {
    'CACHE_TYPE':'simple'#使用内存作为cache
}

#跨域请求
cors_config = {
    "origins": "*", #所有域都允许
    "expose_headers": ["Content-Type", "token","x-requested-with"], #跨域请求头允许的
    "methods": ["GET", "POST","PUT","PATCH","OPTIONS","DELETE"], #跨域允许的请求方式
    "supports_credentials": True, #允许在cookies跨域
}

def create_app():
    #创建一个flask实例，传递__name__ ,是把当前文路径作为flask实例的根路径
    #static和templates都是创建在该路径下的
    app = Flask(__name__,static_folder='../static') #static目录位置是上层的static
    monkey.patch_all()  # 开启补丁机制
    '基本配置'
    #导入配置从类中
    app.config.from_object(envs.get('default'))
    '日志配置'
    # app.logger.addHandler(getLogHandlerFile())
    # app.logger.setLevel(logging.WARNING)
    app.logger.addHandler(getLogHandlerFile())
    app.logger.setLevel(logging.INFO)

    '中间件'
    #每次响应前都先设置好响应头，做好跨域
    app.after_request(after_request) #【1、使用中间件解决跨域】
    #执行请求处理前的中间件
    app.before_request(before_request)


    '拓展配置'
    #配置db对象 将db对象与app进行绑定，orm对象与app绑定
    db.init_app(app)
    #配置restful
    api.init_app(app)
    #配置跨域，supports_credentials=True 允许携带cookies等信息
    cors.init_app(app,**cors_config) #【2、使用三方扩展解决跨域】
    #配置缓存
    cache.init_app(app=app,config=cache_config_redis)


    '蓝图注册'
    #蓝图注册
    app.register_blueprint(user_bp)
    app.register_blueprint(ws_bp)
    app.register_blueprint(resource_bp)

    #异常处理
    @app.errorhandler(Exception)
    def handle_exception(e):
        # 将异常错误写到日志文件中
        app.logger.exception(str(e))
        # print(e, type(e))
        # 对异常错误的响应，使用api的格式
        return jsonify(code=500, message=str(e)), 500

    return app
